﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace DomSharp.ExpressionVisitors
{
    internal class DomMethodCallExpressionVisitor : ExpressionVisitor
    {
        private Stack<string> parameters = new Stack<string>();
        public string VisitResult => $"{instance}.{methodName}({string.Join(",", parameters)})";
        private string methodName;
        private string instance;

        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            methodName = node.Method.Name[0].ToString().ToLower() + node.Method.Name.Substring(1);
            if (node.Object is ConstantExpression constant)
            {
                instance = constant.Type == typeof(Document) ? "document" : throw new ArgumentException();
            }
            else
            {
                throw new ArgumentException();
            }
            return base.VisitMethodCall(node);
        }

        protected override Expression VisitMember(MemberExpression node)
        {
            return base.VisitMember(node);
        }

        protected override Expression VisitConstant(ConstantExpression node)
        {
            if (node.Type == typeof(string))
            {
                parameters.Push($@"""{node.Value?.ToString()}""");
            }
            else if (node.Type == typeof(DateTime) || node.Type == typeof(DateTime?) || node.Type == typeof(DateTimeOffset) || node.Type == typeof(DateTimeOffset?))
            {
                parameters.Push($@"""{node.Value?.ToString()}""");
            }
            else if (node.Type == typeof(IntOrString) || node.Type == typeof(IntOrString?))
            {
                var intOrString = node.Value as IntOrString?;
                if (intOrString.HasValue)
                {
                    if (intOrString.Value.IsString)
                    {
                        parameters.Push($@"""{intOrString.Value.String}""");
                    }
                    else
                    {
                        parameters.Push($@"""{intOrString.Value.Int.ToString()}px""");
                    }
                }
            }
            else if (node.Type.IsValueType || node.Type.IsPrimitive)
            {
                parameters.Push(node.Value?.ToString().ToLower());
            }
            else if (node.Type == typeof(HtmlElement))
            {
                var id = (node.Value as HtmlElement).ElementReference.Id;
                parameters.Push($@"document.getElementById(""{id}"")");
            }
            return base.VisitConstant(node);
        }
    }
}
